package com.flansmod.common.types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import net.minecraft.block.material.Material;
import net.minecraft.client.model.ModelBase;
import net.minecraft.init.Items;
import net.minecraft.item.EnumDyeColor;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.potion.PotionEffect;
import net.minecraft.util.MathHelper;
import net.minecraft.util.WeightedRandomChestContent;
import net.minecraft.world.World;
import net.minecraftforge.common.ChestGenHooks;
import net.minecraftforge.common.DungeonHooks;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.registry.GameRegistry;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import com.flansmod.common.FlansMod;
import com.flansmod.common.guns.Paintjob;
public class InfoType
{
/** infoTypes */
public static HashMap<Integer, InfoType> infoTypes = new HashMap<Integer, InfoType>();
public String contentPack;
public Item item;
public int colour = 0xffffff;
public String iconPath;
public Object[] recipe;
public String[] recipeLine;
public int recipeOutput = 1;
public boolean shapeless;
public String smeltableFrom = null;
public String name;
public String shortName;
public String texture;
public String modelString = null;
public String description;
public float modelScale = 1F;
/** If this is set to false, then this item cannot be dropped */
public boolean canDrop = true;
/** The probability that this item will appear in a dungeon chest.
* Scaled so that each chest is likely to have a fixed number of Flan's Mod items.
* Must be greater than or equal to 0, and should probably not exceed 100 */
public int dungeonChance = 1;
private static Random random = new Random();
/** Used for scaling */
public static int totalDungeonChance = 0;
public InfoType(TypeFile file)
{
contentPack = file.contentPack;
}
public void read(TypeFile file)
{
preRead(file);
for(;;)
{
String line = null;
line = file.readLine();
if(line == null)
break;
if(line.startsWith("//"))
continue;
String[] split = line.split(" ");
if(split.length < 2)
continue;
read(split, file);
}
postRead(file);
infoTypes.put(shortName.hashCode(), this);
totalDungeonChance += dungeonChance;
}
/** Method for performing actions prior to reading the type file */
protected void preRead(TypeFile file) {}
/** Method for performing actions after reading the type file */
protected void postRead(TypeFile file) {}
@SideOnly(Side.CLIENT)
public ModelBase GetModel() { return null; }
/** Pack reader */
protected void read(String[] split, TypeFile file)
{
try
{
// Standard line reads
shortName = Read(split, "ShortName", shortName);
name = ReadAndConcatenateMultipleStrings(split, "Name", name);
description = ReadAndConcatenateMultipleStrings(split, "Description", description);
modelString = Read(split, "Model", modelString);
modelScale = Read(split, "ModelScale", modelScale);
texture = Read(split, "Texture", texture);
iconPath = Read(split, "Icon", iconPath);
dungeonChance = Read(split, "DungeonProbability", dungeonChance);
dungeonChance = Read(split, "DungeonLootChance", dungeonChance);
recipeOutput = Read(split, "RecipeOutput", recipeOutput);
smeltableFrom = Read(split, "SmeltableFrom", smeltableFrom);
canDrop = Read(split, "CanDrop", canDrop);
// More complicated line reads
if (split[0].equals("Colour") || split[0].equals("Color"))
{
colour = (Integer.parseInt(split[1]) << 16) + ((Integer.parseInt(split[2])) << 8) + ((Integer.parseInt(split[3])));
}
if (split[0].equals("Recipe"))
{
recipe = new Object[split.length + 2];
for (int i = 0; i < 3; i++)
{
String line = null;
line = file.readLine();
if (line == null)
{
continue;
}
if (line == null || line.startsWith("//"))
{
i--;
continue;
}
recipe[i] = line;
}
recipeLine = split;
shapeless = false;
}
else if (split[0].equals("ShapelessRecipe"))
{
recipeLine = split;
shapeless = true;
}
}
catch (Exception e)
{
FlansMod.log("Reading file failed : " + shortName);
e.printStackTrace();
}
}
/** -------------------------------------------------------------------------------------------------------- */
/** HELPER FUNCTIONS FOR READING. Should give better debug output */
/** -------------------------------------------------------------------------------------------------------- */
protected boolean KeyMatches(String[] split, String key)
{
return split != null && split.length > 1 && key != null && split[0].toLowerCase().equals(key.toLowerCase());
}
protected int Read(String[] split, String key, int currentValue)
{
if(KeyMatches(split, key))
{
if(split.length == 2)
{
try
{
currentValue = Integer.parseInt(split[1]);
}
catch (Exception e)
{
InfoType.LogError(shortName, "Incorrect format for " + key + ". Passed in value is not an integer");
}
}
else
{
InfoType.LogError(shortName, "Incorrect format for " + key + ". Should be \"" + key + " <integer value>\"");
}
}
return currentValue;
}
protected float Read(String[] split, String key, float currentValue)
{
if(KeyMatches(split, key))
{
if(split.length == 2)
{
try
{
currentValue = Float.parseFloat(split[1]);
}
catch (Exception e)
{
InfoType.LogError(shortName, "Incorrect format for " + key + ". Passed in value is not an float");
}
}
else
{
InfoType.LogError(shortName, "Incorrect format for " + key + ". Should be \"" + key + " <float value>\"");
}
}
return currentValue;
}
protected double Read(String[] split, String key, double currentValue)
{
if(KeyMatches(split, key))
{
if(split.length == 2)
{
try
{
currentValue = Double.parseDouble(split[1]);
}
catch (Exception e)
{
InfoType.LogError(shortName, "Incorrect format for " + key + ". Passed in value is not an float");
}
}
else
{
InfoType.LogError(shortName, "Incorrect format for " + key + ". Should be \"" + key + " <float value>\"");
}
}
return currentValue;
}
protected String Read(String[] split, String key, String currentValue)
{
if(KeyMatches(split, key))
{
if(split.length == 2)
{
currentValue = split[1];
}
else
{
InfoType.LogError(shortName, "Incorrect format for " + key + ". Should be \"" + key + " <singleWord>\"");
}
}
return currentValue;
}
protected String ReadAndConcatenateMultipleStrings(String[] split, String key, String currentValue)
{
if(KeyMatches(split, key))
{
if(split.length > 1)
{
currentValue = split[1];
for (int i = 0; i < split.length - 2; i++)
{
currentValue = currentValue + " " + split[i + 2];
}
}
else
{
InfoType.LogError(shortName, "Incorrect format for " + key + ". Should be \"" + key + " <long string>\"");
}
}
return currentValue;
}
protected boolean Read(String[] split, String key, boolean currentValue)
{
if(KeyMatches(split, key))
{
if(split.length == 2)
{
try
{
currentValue = Boolean.parseBoolean(split[1]);
}
catch (Exception e)
{
InfoType.LogError(shortName, "Incorrect format for " + key + ". Passed in value is not an boolean");
}
}
else
{
InfoType.LogError(shortName, "Incorrect format for " + key + ". Should be \"" + key + " <true/false>\"");
}
}
return currentValue;
}
/** -------------------------------------------------------------------------------------------------------- */
/** */
/** -------------------------------------------------------------------------------------------------------- */
protected static void LogError(String shortName, String s)
{
FlansMod.log("[Problem in " + shortName + ".txt]" + s);
}
@Override
public String toString()
{
return super.getClass().getSimpleName() + ": " + shortName;
}
public void addRecipe()
{
this.addRecipe(getItem());
}
/** Reimported from old code */
public void addRecipe(Item par1Item)
{
if (smeltableFrom != null)
{
GameRegistry.addSmelting(getRecipeElement(smeltableFrom, 0), new ItemStack(item), 0.0F);
}
if (recipeLine == null)
return;
try
{
if (!shapeless)
{
// Fix oversized recipes
int rows = 3;
// First column
if (((String) recipe[0]).charAt(0) == ' ' && ((String) recipe[1]).charAt(0) == ' ' && ((String) recipe[2]).charAt(0) == ' ')
{
for (int i = 0; i < 3; i++)
recipe[i] = ((String) recipe[i]).substring(1);
// New first column
if (((String) recipe[0]).charAt(0) == ' ' && ((String) recipe[1]).charAt(0) == ' ' && ((String) recipe[2]).charAt(0) == ' ')
{
for (int i = 0; i < 3; i++)
recipe[i] = ((String) recipe[i]).substring(1);
}
}
// Last column
int last = ((String) recipe[0]).length() - 1;
if (((String) recipe[0]).charAt(last) == ' ' && ((String) recipe[1]).charAt(last) == ' ' && ((String) recipe[2]).charAt(last) == ' ')
{
for (int i = 0; i < 3; i++)
recipe[i] = ((String) recipe[i]).substring(0, last);
// New last column
last--;
if (((String) recipe[0]).charAt(last) == ' ' && ((String) recipe[1]).charAt(last) == ' ' && ((String) recipe[2]).charAt(last) == ' ')
{
for (int i = 0; i < 3; i++)
recipe[i] = ((String) recipe[i]).substring(0, 0);
}
}
// Top row
if (recipe[0].equals(" ") || recipe[0].equals(" ") || recipe[0].equals(" "))
{
Object[] newRecipe = new Object[recipe.length - 1];
newRecipe[0] = recipe[1];
newRecipe[1] = recipe[2];
recipe = newRecipe;
rows--;
// Next top row
if (recipe[0].equals(" ") || recipe[0].equals(" ") || recipe[0].equals(" "))
{
Object[] newRecipe1 = new Object[recipe.length - 1];
newRecipe1[0] = recipe[1];
recipe = newRecipe1;
rows--;
}
}
// Bottom row
if (recipe[rows - 1].equals(" ") || recipe[rows - 1].equals(" ") || recipe[rows - 1].equals(" "))
{
Object[] newRecipe = new Object[recipe.length - 1];
newRecipe[0] = recipe[0];
newRecipe[1] = recipe[1];
recipe = newRecipe;
rows--;
// Next bottom row
if (recipe[rows - 1].equals(" ") || recipe[rows - 1].equals(" ") || recipe[rows - 1].equals(" "))
{
Object[] newRecipe1 = new Object[recipe.length - 1];
newRecipe1[0] = recipe[0];
recipe = newRecipe1;
rows--;
}
}
for (int i = 0; i < (recipeLine.length - 1) / 2; i++)
{
recipe[i * 2 + rows] = recipeLine[i * 2 + 1].charAt(0);
recipe[i * 2 + rows + 1] = getRecipeElement(recipeLine[i * 2 + 2]);
}
GameRegistry.addRecipe(new ItemStack(item, recipeOutput), recipe);
} else
{
recipe = new Object[recipeLine.length - 1];
for (int i = 0; i < (recipeLine.length - 1); i++)
{
recipe[i] = getRecipeElement(recipeLine[i + 1]);
}
GameRegistry.addShapelessRecipe(new ItemStack(item, recipeOutput), recipe);
}
} catch (Exception e)
{
FlansMod.log("Failed to add recipe for : " + shortName);
e.printStackTrace();
}
}
/** Return a dye damage value from a string name */
protected int getDyeDamageValue(String dyeName)
{
int damage = -1;
for(int i = 0; i < EnumDyeColor.values().length; i++)
{
if(EnumDyeColor.byDyeDamage(i).getUnlocalizedName().equals(dyeName))
damage = i;
}
if(damage == -1)
FlansMod.log("Failed to find dye colour : " + dyeName + " while adding " + contentPack);
return damage;
}
public Item getItem()
{
return item;
}
public static ItemStack getNonRecipeElement(String str)
{
// Split ID with . and if it contains a second part, use it
// as damage value.
if (str.contains("."))
return getRecipeElement(str.split("\\.")[0], Integer.valueOf(str.split("\\.")[1]));
else
return getRecipeElement(str, 0);
}
public static ItemStack getRecipeElement(String str)
{
// Split ID with . and if it contains a second part, use it
// as damage value.
if (str.contains("."))
return getRecipeElement(str.split("\\.")[0], Integer.valueOf(str.split("\\.")[1]));
else
return getRecipeElement(str, 32767);
}
public static ItemStack getRecipeElement(String s, int damage)
{
return getRecipeElement(s, 1, damage);
}
public static ItemStack getRecipeElement(String s, int amount, int damage)
{
return getRecipeElement(s, amount, damage, "nothing");
}
public static ItemStack getRecipeElement(String s, int amount, int damage, String requester)
{
if (s.equals("doorIron"))
{
return new ItemStack(Items.iron_door, amount);
}
if (s.equals("clayItem"))
{
return new ItemStack(Items.clay_ball, amount);
}
for(Object object : Item.itemRegistry)
{
Item item = (Item)object;
if (item != null && item.getUnlocalizedName() != null && (item.getUnlocalizedName().equals("item." + s) || item.getUnlocalizedName().equals("tile." + s)))
{
return new ItemStack(item, amount, damage);
}
}
for(InfoType type : infoTypes.values())
{
if(type.shortName.equals(s))
return new ItemStack(type.item, amount, damage);
}
if (s.equals("gunpowder"))
{
return new ItemStack(Items.gunpowder, amount);
}
if (s.equals("iron"))
{
return new ItemStack(Items.iron_ingot, amount);
}
FlansMod.log("Could not find " + s + " when adding recipe for " + requester);
return null;
}
/** To be overriden by subtypes for model reloading */
public void reloadModel()
{
}
@Override
public int hashCode()
{
return shortName.hashCode();
}
public static InfoType getType(String s)
{
return infoTypes.get(s.hashCode());
}
public static InfoType getType(int hash)
{
return infoTypes.get(hash);
}
public void onWorldLoad(World world)
{
}
public static InfoType getType(ItemStack itemStack)
{
if(itemStack == null)
return null;
Item item = itemStack.getItem();
if(item instanceof IFlanItem)
return ((IFlanItem)item).getInfoType();
return null;
}
public static PotionEffect getPotionEffect(String[] split)
{
int potionID = Integer.parseInt(split[1]);
int duration = Integer.parseInt(split[2]);
int amplifier = Integer.parseInt(split[3]);
return new PotionEffect(potionID, duration, amplifier, false, false);
}
public static Material getMaterial(String mat)
{
return Material.ground;
}
public void addDungeonLoot()
{
if(dungeonChance > 0)
{
ItemStack stack = new ItemStack(this.item);
addToRandomChest(stack, (float)(FlansMod.dungeonLootChance * dungeonChance) / (float)totalDungeonChance);
}
}
protected void addToRandomChest(ItemStack stack, float rawChance)
{
if(rawChance >= 1 || random.nextFloat() < rawChance)
{
int chance = MathHelper.ceiling_float_int(rawChance);
switch(random.nextInt(10))
{
case 0 : ChestGenHooks.addItem(ChestGenHooks.DUNGEON_CHEST, new WeightedRandomChestContent(new ItemStack(this.item), 1, 1, chance)); break;
case 1 : ChestGenHooks.addItem(ChestGenHooks.MINESHAFT_CORRIDOR, new WeightedRandomChestContent(new ItemStack(this.item), 1, 1, chance)); break;
case 2 : ChestGenHooks.addItem(ChestGenHooks.PYRAMID_DESERT_CHEST, new WeightedRandomChestContent(new ItemStack(this.item), 1, 1, chance)); break;
case 3 : ChestGenHooks.addItem(ChestGenHooks.PYRAMID_JUNGLE_CHEST, new WeightedRandomChestContent(new ItemStack(this.item), 1, 1, chance)); break;
case 4 : ChestGenHooks.addItem(ChestGenHooks.STRONGHOLD_CORRIDOR, new WeightedRandomChestContent(new ItemStack(this.item), 1, 1, chance)); break;
case 5 : ChestGenHooks.addItem(ChestGenHooks.STRONGHOLD_LIBRARY, new WeightedRandomChestContent(new ItemStack(this.item), 1, 1, chance)); break;
case 6 : ChestGenHooks.addItem(ChestGenHooks.STRONGHOLD_CROSSING, new WeightedRandomChestContent(new ItemStack(this.item), 1, 1, chance)); break;
case 7 : ChestGenHooks.addItem(ChestGenHooks.VILLAGE_BLACKSMITH, new WeightedRandomChestContent(new ItemStack(this.item), 1, 1, chance)); break;
case 8 : ChestGenHooks.addItem(ChestGenHooks.BONUS_CHEST, new WeightedRandomChestContent(new ItemStack(this.item), 1, 1, chance)); break;
case 9 : ChestGenHooks.addItem(ChestGenHooks.NETHER_FORTRESS, new WeightedRandomChestContent(new ItemStack(this.item), 1, 1, chance)); break;
}
}
}
}